package com.sunchangming.uniqname;

import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import com.google.protobuf.BlockingService;
import com.google.protobuf.CodedInputStream;

public class ProtobufDecoder extends CumulativeProtocolDecoder {
	private final static Logger logger = Logger.getLogger(ProtobufDecoder.class);
	private final BlockingService service;
	private final boolean isServer;

	public ProtobufDecoder(BlockingService service, boolean isServer) {
		super();
		this.service = service;
		this.isServer = isServer;
	}

	@Override
	protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
		in.mark();
		int remain = in.remaining();
		if (remain > 2) {
			// 最前面是固定的2字节的长度。
			int length = (in.get() << 8) + in.get();
			if (remain < length + 2) {
				in.reset();
				return false;
			}
			byte[] buffer = new byte[length];
			in.get(buffer);
			try {
				CodedInputStream is = CodedInputStream.newInstance(buffer);
				// 然后是method id
				int type = is.readInt32();

				if (service.getDescriptorForType().getMethods().size() <= type || type < 0) {
					logger.error("错误的数据包，type=" + type);
					// 这个时候应该关闭连接。
					session.close(true);
					return true;
				}
				com.google.protobuf.Descriptors.MethodDescriptor md = service.getDescriptorForType().getMethods()
						.get(type);
				final com.google.protobuf.Message.Builder builder;
				if (isServer)
					builder = service.getRequestPrototype(md).newBuilderForType();
				else
					builder = service.getResponsePrototype(md).newBuilderForType();
				com.google.protobuf.Message msg = builder.mergeFrom(is).build();
				out.write(new Res(msg, type));
			} catch (java.io.IOException ex) {
				session.close(true);
				return true;
			}
			return true;
		}
		return false;
	}

}
